#include <algorithm/analytical_model/algorithm/cpu/VectorConvert.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/heliostat/RectangleHeliostat.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/utils/convert/heliostat/ConvertHeliostat.h>
#include <algorithm/analytical_model/algorithm/geometry/Rectangle3D.h>
#include <algorithm/shared/data/scene/Heliostat.h>
#include <algorithm/shared/data/topology/geometry/Rectangle3D.h>

#include <utils/ParaUtils.h>
#include <utils/Format.h>

using namespace solar::cuda::inter_op;

template <>
void solar::cuda::inter_op::convertHeliostat(RectangleHeliostat* input_ptr, Heliostat* output_ptr)
{
    auto input = *input_ptr;
    auto output = *output_ptr;
    auto vertices = input.getVertices();
    const auto normal = input.getNormal();
    const auto input_size = input.getSize();
    const auto center = input.getPosition();
    const auto geometry_heliostat = SOLAR_GET_VALUE(Heliostat, geometry_, output);
    std::array<Vec3, 4> new_vertices = {cpu::toVec3(vertices[0]), cpu::toVec3(vertices[1]),
                                        cpu::toVec3(vertices[2]), cpu::toVec3(vertices[3])};
    auto *rectangle_geometry = dynamic_cast<Rectangle3D*>(geometry_heliostat.get());
    SOLAR_SET_VALUE(Rectangle3D, vertices_, new_vertices, *rectangle_geometry)
    SOLAR_SET_VALUE(Rectangle3D, size_, cpu::toVec3(input_size), *rectangle_geometry)
    SOLAR_SET_VALUE(Rectangle3D, normal_, cpu::toVec3(normal), *rectangle_geometry)
    SOLAR_SET_VALUE(Rectangle3D, center_, cpu::toVec3(center), *rectangle_geometry)
}

template <>
void solar::cuda::inter_op::convertHeliostat(Heliostat* input_ptr, RectangleHeliostat* output_ptr)
{
    auto geometry_heliostat = SOLAR_GET_VALUE(Heliostat, geometry_, *input_ptr);
    auto rectangle_geometry = *(dynamic_cast<Rectangle3D*>(geometry_heliostat.get()));
    auto size = cpu::toFloat3(SOLAR_GET_VALUE(Rectangle3D, size_, rectangle_geometry));
    output_ptr->setSize(size);
    output_ptr->setPosition(cpu::toFloat3(solar::center(std::addressof(rectangle_geometry))));
}
